package pl.enigmatic.validation.util;

import static pl.enigmatic.validation.util.Util.*;
import pl.enigmatic.validation.SimpleValidator;


public abstract class DoubleValidator implements SimpleValidator<Double> {

	public static final SimpleValidator<Double> NOT_NULL = new NotNull<Double>();

	public static final DoubleValidator LT(final double max) {
		return new DoubleValidator() {

			@Override
			public boolean isValueValid(final Double val) {
				return NOT_NULL.isValueValid(val) && val < max;
			}
		};
	}

	public static final DoubleValidator LE(final double max) {
		return new DoubleValidator() {

			@Override
			public boolean isValueValid(final Double val) {
				return NOT_NULL.isValueValid(val) && val <= max;
			}
		};
	}

	public static final DoubleValidator GT(final double min) {
		return new DoubleValidator() {

			@Override
			public boolean isValueValid(final Double val) {
				return NOT_NULL.isValueValid(val) && val > min;
			}
		};
	}

	public static final DoubleValidator GE(final double min) {
		return new DoubleValidator() {

			@Override
			public boolean isValueValid(final Double val) {
				return NOT_NULL.isValueValid(val) && val >= min;
			}
		};
	}

	public static final DoubleValidator BETWEEN(final double min, final double max) {
		return new DoubleValidator() {

			private final DoubleValidator le = LE(max);
			private final DoubleValidator ge = GE(min);

			@Override
			public boolean isValueValid(final Double val) {
				return le.isValueValid(val) && ge.isValueValid(val);
			}
		};
	}

	@SuppressWarnings("unchecked")
	public static final SimpleValidator<Double> OUTSIDE(final double min, final double max) {
		return AND(NOT_NULL, NOT(BETWEEN(min, max)));
	}

	private DoubleValidator() {}

}
